#ifndef __GTK_UI_H__
#define __GTK_UI_H__

#include <string.h>
#include <iostream>
#include <string>

// TINYXML :  1
// TINYXML2:  2
// LIBXML2 :  3
// RAPIDXML:  4
// PUGIXML :  5
// libroxml:  6
#ifndef XML_LIBRARY
  #define XML_LIBRARY  4
#endif

// 预先声明，后续根据引用的库不同，特例化成相应版本
#if 1
template<typename XmlDoc, typename XmlNode>
static const char* _get_name(XmlDoc doc, XmlNode node);

template<typename XmlDoc, typename XmlNode>
static const char* _get_value(XmlDoc doc, XmlNode node);

template<typename XmlDoc, typename XmlNode>
static bool        _is_comment_node(XmlDoc doc, XmlNode node);

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_first_child(XmlDoc doc, XmlNode node);

template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_next_child(XmlDoc doc, XmlNode node, XmlNode child);

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_parent(XmlDoc doc, XmlNode node);

template<typename XmlDoc, typename XmlNode>
static bool        _has_child_node(XmlDoc doc, XmlNode node, const char* name);

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_child_node(XmlDoc doc, XmlNode node, const char* name);

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_first_attribute(XmlDoc doc, XmlNode node);

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_next_attribute(XmlDoc doc, XmlNode node, XmlAttr attr);

template<typename XmlDoc, typename XmlNode>
static bool        _has_attribute(XmlDoc doc, XmlNode node, const char* name);

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_attribute(XmlDoc doc, XmlNode node, const char* name);

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_name(XmlDoc doc, XmlNode node, XmlAttr attr);

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_value(XmlDoc doc, XmlNode node, XmlAttr attr);

template<typename XmlDoc, typename XmlNode>
XmlDoc _load_gtk_ui(const char* file_name);

template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_root(XmlDoc gtk_ui_doc);

template<typename XmlDoc, typename XmlNode>
void _release_gtk_ui(XmlDoc doc);

#endif

// 这儿使用tinyxml
#if XML_LIBRARY == 1

#include <tinyxml.h>

#pragma comment(lib, "tinyxmlSTL.lib")

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_name(XmlDoc doc, XmlNode node)
{
    return node->Value();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_value(XmlDoc doc, XmlNode node)
{
    // 正常应该有一个子结点，存放相应的value，如果没有，则应该是形式<aaa name="" />
    if (node->FirstChild() && node->FirstChild()->ToText()) {
        return node->FirstChild()->Value();
    }

    return "";//node->Value();
}
//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static bool        _is_comment_node(XmlDoc doc, XmlNode node)
{
    if (NULL == node->ToComment()) {
        return false;
    }
    return true;
}
//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_first_child(XmlDoc doc, XmlNode node)
{
    return node->FirstChildElement();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_next_child(XmlDoc doc, XmlNode node, XmlNode child)
{
    return child->NextSiblingElement();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_parent(XmlDoc doc, XmlNode node)
{
    return node->Parent()->ToElement();
}

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return node->FirstChildElement(name);
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return node->FirstChildElement(name) != nullptr;
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return node->Attribute(name) != nullptr;
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*, typename XmlAttr = TiXmlAttribute*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_first_attribute(XmlDoc doc, XmlNode node)
{
    return node->FirstAttribute();
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    XmlAttr attr = node->FirstAttribute();
    while (attr)
    {
        if (strcmp(attr->Name(), name) == 0)
            return attr;
        attr = attr->Next();
    }
    return NULL;
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*, typename XmlAttr = TiXmlAttribute*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_name(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->Name();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*, typename XmlAttr = TiXmlAttribute*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_value(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->Value();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*, typename XmlAttr = TiXmlAttribute*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_next_attribute(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->Next();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
XmlDoc _load_gtk_ui(const char* file_name)
{
    if (NULL == file_name) {
        return nullptr;
    }

    TiXmlDocument* doc = new TiXmlDocument;
    if (!doc) {
        return nullptr;
    }
    //获取树形结构
    if (!doc->LoadFile(file_name)) {
        delete doc;
        return nullptr;
    }
    return doc;
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_root(XmlDoc gtk_ui_doc)
{
    if (nullptr == gtk_ui_doc) {
        return nullptr;
    }

    //获取根节点
    TiXmlElement* root = gtk_ui_doc->RootElement();
    return root;
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
void _release_gtk_ui(XmlDoc gtk_ui_doc)
{
    delete gtk_ui_doc;
}

typedef TiXmlDocument*      GtkUiXmlDoc;
typedef TiXmlElement*       GtkUiXmlNode;
typedef TiXmlAttribute*     GtkUiXmlAttr;

// 这儿使用tinyxml2
#elif XML_LIBRARY == 2

#include <tinyxml2.h>

#pragma comment(lib, "tinyxml2.lib ")

using namespace tinyxml2;

//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_name(XmlDoc doc, XmlNode node)
{
    return node->Value(); //"element";// node->name();
}

//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_value(XmlDoc doc, XmlNode node)
{
    // 正常应该有一个子结点，存放相应的value，如果没有，则应该是形式<aaa name="" />
    if (node->FirstChild() && node->FirstChild()->ToText()) {
        return node->FirstChild()->Value();
    }

    return "";//node->Value();
}
//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*>
template<typename XmlDoc, typename XmlNode>
static bool        _is_comment_node(XmlDoc doc, XmlNode node)
{
    if (NULL == node->ToComment()) {
        return false;
    }
    return true;
}
//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_first_child(XmlDoc doc, XmlNode node)
{
    return node->FirstChildElement();
}
//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_next_child(XmlDoc doc, XmlNode node, XmlNode child)
{
    return child->NextSiblingElement();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_parent(XmlDoc doc, XmlNode node)
{
    return node->Parent()->ToElement();
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return node->FirstChildElement(name) != nullptr;
}

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return node->FirstChildElement(name);
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return node->Attribute(name) != nullptr;
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return (XmlAttr)(node->FindAttribute(name));
}

//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*, typename XmlAttr = XMLAttribute*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_first_attribute(XmlDoc doc, XmlNode node)
{
    return (XMLAttribute*)(node->FirstAttribute());
}
//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*, typename XmlAttr = XMLAttribute*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_name(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->Name();
}
//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*, typename XmlAttr = XMLAttribute*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_value(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->Value();
}
//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*, typename XmlAttr = XMLAttribute*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_next_attribute(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return (XMLAttribute *)(attr->Next());
}

//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*>
template<typename XmlDoc, typename XmlNode>
XmlDoc _load_gtk_ui(const char* file_name)
{
    if (NULL == file_name) {
        return nullptr;
    }

    XMLDocument* doc = new XMLDocument;
    if (!doc) {
        return nullptr;
    }
    //获取树形结构
    if (0 != doc->LoadFile(file_name)) {
        delete doc;
        return nullptr;
    }
    return doc;
}

//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*>
template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_root(XmlDoc gtk_ui_doc)
{
    if (nullptr == gtk_ui_doc) {
        return nullptr;
    }

    //获取根节点
    XMLElement* root = gtk_ui_doc->RootElement();
    return root;
}

//template<typename XmlDoc = XMLDocument*, typename XmlNode = XMLElement*>
template<typename XmlDoc, typename XmlNode>
void _release_gtk_ui(XmlDoc doc)
{
    delete doc;
}

typedef XMLDocument*      GtkUiXmlDoc;
typedef XMLElement*       GtkUiXmlNode;
typedef XMLAttribute*     GtkUiXmlAttr;


// 使用libxml2
#elif XML_LIBRARY == 3

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/xmlstring.h>

#pragma comment(lib, "libxml2.lib ")

//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_name(XmlDoc doc, XmlNode node)
{
    return (const char*)(node->name);
}
//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_value(XmlDoc doc, XmlNode node)
{
    if ((node->xmlChildrenNode != NULL) && (node->xmlChildrenNode->type == XML_TEXT_NODE)) {
        return (const char*)(node->xmlChildrenNode->content);
    }

    return "";
}
//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*>
template<typename XmlDoc, typename XmlNode>
static bool        _is_comment_node(XmlDoc doc, XmlNode node)
{
    if (node->type == XML_COMMENT_NODE){
        return true;
    }
    return false;
}
//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_first_child(XmlDoc doc, XmlNode node)
{
#if 0
    if ((node->xmlChildrenNode != NULL) && (node->xmlChildrenNode->type == XML_TEXT_NODE)) {
        return node->xmlChildrenNode->next;
    }

    return node->xmlChildrenNode;
#else
    return xmlFirstElementChild(node);
#endif
}
//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_next_child(XmlDoc doc, XmlNode node, XmlNode child)
{
#if 0
    if ((child->next != NULL) && (child->next->type == XML_TEXT_NODE)) {
        return child->next->next;
    }

    return child->next;
#else
    return xmlNextElementSibling(child);
#endif
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_parent(XmlDoc doc, XmlNode node)
{
    return node->parent;
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    XmlNode child = _get_first_child(doc, node);
    while (child != NULL) {
        if (strcmp(_get_name(doc, child), name) == 0) {
            return true;
        }

        child = _get_next_child(doc, node, child);
    }
    return false;
}

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    XmlNode child = _get_first_child(doc, node);
    while (child != NULL) {
        if (strcmp(_get_name(doc, child), name) == 0) {
            return child;
        }

        child = _get_next_child(doc, node, child);
    }
    return nullptr;
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return xmlHasProp(node, (const xmlChar*)name) != NULL;
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return xmlHasProp(node, (const xmlChar*)name);
}

//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*, typename XmlAttr = xmlAttr*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_first_attribute(XmlDoc doc, XmlNode node)
{
    return node->properties;
}
//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*, typename XmlAttr = xmlAttr*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_name(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return (const char*)(attr->name);
}
//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*, typename XmlAttr = xmlAttr*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_value(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return (const char*)(attr->children->content);
}
//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*, typename XmlAttr = xmlAttr*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_next_attribute(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->next;
}

//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*>
template<typename XmlDoc, typename XmlNode>
XmlDoc _load_gtk_ui(const char* file_name)
{
    if (NULL == file_name) {
        return nullptr;
    }

    xmlDoc* doc = xmlParseFile(file_name);
    if (!doc) {
        return nullptr;
    }
    return doc;
}

//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*>
template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_root(XmlDoc gtk_ui_doc)
{
    if (nullptr == gtk_ui_doc) {
        return nullptr;
    }

    //获取根节点
    XmlNode root = xmlDocGetRootElement(gtk_ui_doc);
    if (root == NULL) {
        return nullptr;
    }
    return root;
}

//template<typename XmlDoc = xmlDoc*, typename XmlNode = xmlNode*>
template<typename XmlDoc, typename XmlNode>
void _release_gtk_ui(XmlDoc doc)
{
    xmlFreeDoc(doc);
    xmlCleanupParser();
}

typedef xmlDoc*      GtkUiXmlDoc;
typedef xmlNode*     GtkUiXmlNode;
typedef xmlAttr*     GtkUiXmlAttr;

// 使用rapidxml
#elif XML_LIBRARY == 4

#include <rapidxml/rapidxml.hpp>
#include <rapidxml/rapidxml_utils.hpp>

using namespace rapidxml;

//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_name(XmlDoc doc, XmlNode node)
{
    return node->name();
}
//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_value(XmlDoc doc, XmlNode node)
{
    return node->value();
}
//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*>
template<typename XmlDoc, typename XmlNode>
static bool        _is_comment_node(XmlDoc doc, XmlNode node)
{
    if (node_type::node_comment == node->type()) {
        return true;
    }
    return false;
}
//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_first_child(XmlDoc doc, XmlNode node)
{
    return node->first_node();
}
//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_next_child(XmlDoc doc, XmlNode node, XmlNode child)
{
    return child->next_sibling();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_parent(XmlDoc doc, XmlNode node)
{
    return node->parent();
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return node->first_node(name) != NULL;
}

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return node->first_node(name);
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return node->first_attribute(name);
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return node->first_attribute(name) != NULL;
}

//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*, typename XmlAttr = xml_attribute<>*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_first_attribute(XmlDoc doc, XmlNode node)
{
    return node->first_attribute();
}
//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*, typename XmlAttr = xml_attribute<>*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_name(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->name();
}
//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*, typename XmlAttr = xml_attribute<>*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_value(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->value();
}
//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*, typename XmlAttr = xml_attribute<>*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_next_attribute(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return attr->next_attribute();
}

typedef struct LuaXmlDoc{
    file<>* fdoc;
    xml_document<>* xml_doc;
}LuaXmlDoc;

//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*>
template<typename XmlDoc, typename XmlNode>
XmlDoc _load_gtk_ui(const char* file_name)
{
    if (NULL == file_name) {
        return nullptr;
    }

    //file<> fdoc(file_name);
    XmlDoc full_doc = new LuaXmlDoc;
    full_doc->fdoc = new file<>(file_name);
    full_doc->xml_doc = new xml_document<>();
    //获取树形结构
    try {
        xml_document<>* xml_doc = full_doc->xml_doc;
        xml_doc->parse<0>(full_doc->fdoc->data());
    }
    catch (...) {
        delete full_doc->fdoc;
        delete full_doc->xml_doc;
        delete full_doc;
        return nullptr;
    }
    return full_doc;
}

//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*>
template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_root(XmlDoc gtk_ui_doc)
{
    if (nullptr == gtk_ui_doc) {
        return nullptr;
    }

    //获取根节点
    XmlNode root = gtk_ui_doc->xml_doc->first_node();
    return root;
}

//template<typename XmlDoc = xml_document<>*, typename XmlNode = xml_node<>*>
template<typename XmlDoc, typename XmlNode>
void _release_gtk_ui(XmlDoc full_doc)
{
    delete full_doc->xml_doc;
    delete full_doc->fdoc;
    delete full_doc;
}

typedef LuaXmlDoc*          GtkUiXmlDoc;
typedef xml_node<>*         GtkUiXmlNode;
typedef xml_attribute<>*    GtkUiXmlAttr;

// 使用pugixml
#elif XML_LIBRARY == 5

#include <pugixml.hpp>
#include <deque>

using namespace pugi;

//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node>
template<typename XmlDoc, typename XmlNode>
static const char* _get_name(XmlDoc doc, XmlNode node)
{
    return xml_node(node).name(); //"element";// node->name();
}
//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node>
template<typename XmlDoc, typename XmlNode>
static const char* _get_value(XmlDoc doc, XmlNode node)
{
#if 1
    xml_node childNode = xml_node(node).first_child();
    if ((!childNode.empty()) && (childNode.type() == xml_node_type::node_pcdata)) {
        return childNode.value();
    }
    return xml_node(node).value();
#else
    return node.value();
    //return node->text().get();
#endif
}
//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node>
template<typename XmlDoc, typename XmlNode>
static bool        _is_comment_node(XmlDoc doc, XmlNode node)
{
    if (xml_node_type::node_comment == xml_node(node).type()) {
        return true;
    }
    return false;
}
//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_first_child(XmlDoc doc, XmlNode node)
{
    return xml_node(node).first_child().internal_object();
}
//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_next_child(XmlDoc doc, XmlNode node, XmlNode child)
{
    return xml_node(child).next_sibling().internal_object();
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_parent(XmlDoc doc, XmlNode node)
{
    return xml_node(node).parent().internal_object();
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return xml_node(node).child(name) != nullptr;
}

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return xml_node(node).child(name).internal_object();
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return xml_node(node).attribute(name).internal_object();
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return xml_node(node).attribute(name) != nullptr;
}

//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node, typename XmlAttr = xml_attribute>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_first_attribute(XmlDoc doc, XmlNode node)
{
    return xml_node(node).first_attribute().internal_object();
}
//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node, typename XmlAttr = xml_attribute>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_name(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return xml_attribute(attr).name();
}
//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node, typename XmlAttr = xml_attribute>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_value(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return xml_attribute(attr).value();
}
//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node, typename XmlAttr = xml_attribute>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_next_attribute(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return xml_attribute(attr).next_attribute().internal_object();
}

//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node>
template<typename XmlDoc, typename XmlNode>
XmlDoc _load_gtk_ui(const char* file_name)
{
    if (NULL == file_name) {
        return nullptr;
    }
    pugi::xml_document* doc = new pugi::xml_document();

    //获取树形结构
    xml_parse_result result = doc->load_file(file_name);
    if (!result) {
        delete doc;
        return nullptr;
    }

    return doc;
}

//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node>
template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_root(XmlDoc gtk_ui_doc)
{
    if (nullptr == gtk_ui_doc) {
        return nullptr;
    }

    //获取根节点
    return gtk_ui_doc->first_child().internal_object();
}

//template<typename XmlDoc = xml_document*, typename XmlNode = xml_node>
template<typename XmlDoc, typename XmlNode>
void _release_gtk_ui(XmlDoc doc)
{
    delete doc;
}

typedef xml_document*           GtkUiXmlDoc;
typedef xml_node_struct*        GtkUiXmlNode;
typedef xml_attribute_struct*   GtkUiXmlAttr;


// 使用libroxml
#elif XML_LIBRARY == 6

#include "roxml.h"

inline node_t *roxml_get_chld(node_t *n, char *name, int nth)
{
	return roxml_get_nodes(n, ROXML_ELM_NODE, name, nth);
}

//template<typename XmlDoc = node_t*, typename XmlNode = node_t*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_name(XmlDoc doc, XmlNode node)
{
    return roxml_get_name(node, NULL, 1);
}
//template<typename XmlDoc = node_t*, typename XmlNode = node_t*>
template<typename XmlDoc, typename XmlNode>
static const char* _get_value(XmlDoc doc, XmlNode node)
{
    return (const char*)roxml_get_content(node, NULL, 1, NULL);
}
//template<typename XmlDoc = node_t*, typename XmlNode = node_t*>
template<typename XmlDoc, typename XmlNode>
static bool        _is_comment_node(XmlDoc doc, XmlNode node)
{
    if (ROXML_CMT_NODE == roxml_get_type(node)) {
        return true;
    }
    return false;
}
//template<typename XmlDoc = node_t*, typename XmlNode = node_t*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_first_child(XmlDoc doc, XmlNode node)
{
    return roxml_get_chld(node, NULL, 0);
}
//template<typename XmlDoc = node_t*, typename XmlNode = node_t*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_next_child(XmlDoc doc, XmlNode node, XmlNode child)
{
    return roxml_get_next_sibling(child);
}

//template<typename XmlDoc = TiXmlDocument*, typename XmlNode = TiXmlElement*>
template<typename XmlDoc, typename XmlNode>
static XmlNode     _get_parent(XmlDoc doc, XmlNode node)
{
    return roxml_get_parent(node);
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return roxml_get_chld(node, (char*)name, 0) != nullptr;
}

template<typename XmlDoc, typename XmlNode> 
static XmlNode     _get_child_node(XmlDoc doc, XmlNode node, const char* name)
{
    return roxml_get_chld(node, (char*)name, 0);
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return roxml_get_attr(node, (char*)name, 0);
}

template<typename XmlDoc, typename XmlNode>
static bool     _has_attribute(XmlDoc doc, XmlNode node, const char* name)
{
    return roxml_get_attr(node, (char*)name, 0) != nullptr;
}

//template<typename XmlDoc = node_t*, typename XmlNode = node_t*, typename XmlAttr = node_t*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_first_attribute(XmlDoc doc, XmlNode node)
{
    return roxml_get_attr(node, NULL, 0);
}
//template<typename XmlDoc = node_t*, typename XmlNode = node_t*, typename XmlAttr = node_t*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_name(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return roxml_get_name(attr, NULL, 1);
}
//template<typename XmlDoc = node_t*, typename XmlNode = node_t*, typename XmlAttr = node_t*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static const char* _get_attribute_value(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return roxml_get_content(attr, NULL, 1, NULL);
}
//template<typename XmlDoc = node_t*, typename XmlNode = node_t*, typename XmlAttr = node_t*>
template<typename XmlDoc, typename XmlNode, typename XmlAttr>
static XmlAttr     _get_next_attribute(XmlDoc doc, XmlNode node, XmlAttr attr)
{
    return roxml_get_attr(node, NULL, roxml_get_node_position(attr) + 1);
}

//template<typename XmlDoc = node_t*, typename XmlNode = node_t*>
template<typename XmlDoc, typename XmlNode>
XmlDoc _load_gtk_ui(const char* file_name)
{
    if (NULL == file_name) {
        return nullptr;
    }

    //获取树形结构
    node_t* doc = roxml_load_doc((char*)file_name);
    if (!doc) {
        return nullptr;
    }

    return doc;
}

//template<typename XmlDoc = node_t*, typename XmlNode = node_t*>
template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_root(XmlDoc gtk_ui_doc)
{
    if (nullptr == gtk_ui_doc) {
        return nullptr;
    }

    //获取根节点
    return roxml_get_chld(gtk_ui_doc, NULL, 0);
}

//template<typename XmlDoc = node_t*, typename XmlNode = node_t*>
template<typename XmlDoc, typename XmlNode>
void _release_gtk_ui(XmlDoc doc)
{
    roxml_release(RELEASE_ALL);
    roxml_close(doc);
}

typedef node_t*     GtkUiXmlDoc;
typedef node_t*     GtkUiXmlNode;
typedef node_t*     GtkUiXmlAttr;

#else
  #error "No XML library selected!"
#endif

template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_first_child(XmlDoc gtk_ui_doc, XmlNode node)
{
    return _get_first_child(gtk_ui_doc, node);
}

template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_next_child(XmlDoc gtk_ui_doc, XmlNode node, XmlNode child)
{
    return _get_next_child(gtk_ui_doc, node, child);
}

template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_parent(XmlDoc gtk_ui_doc, XmlNode node)
{
    return _get_parent(gtk_ui_doc, node);
}

template<typename XmlDoc, typename XmlNode>
bool _get_gtk_ui_has_child_node(XmlDoc gtk_ui_doc, XmlNode node, const char* name)
{
    return _has_child_node(gtk_ui_doc, node, name);
}

template<typename XmlDoc, typename XmlNode>
XmlNode _get_gtk_ui_get_child_node(XmlDoc gtk_ui_doc, XmlNode node, const char* name)
{
    return _get_child_node(gtk_ui_doc, node, name);
}

template<typename XmlDoc, typename XmlNode>
const char* _get_gtk_ui_node_name(XmlDoc gtk_ui_doc, XmlNode node)
{
    return _get_name(gtk_ui_doc, node);
}

template<typename XmlDoc, typename XmlNode>
const char* _get_gtk_ui_node_value(XmlDoc gtk_ui_doc, XmlNode node)
{
    return _get_value(gtk_ui_doc, node);
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
XmlAttr _get_gtk_ui_first_property(XmlDoc gtk_ui_doc, XmlNode node)
{
    return _get_first_attribute<XmlDoc, XmlNode, XmlAttr>(gtk_ui_doc, node);
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
XmlAttr _get_gtk_ui_next_property(XmlDoc gtk_ui_doc, XmlNode node, XmlAttr attr)
{
    return _get_next_attribute<XmlDoc, XmlNode, XmlAttr>(gtk_ui_doc, node, attr);
}

template<typename XmlDoc, typename XmlNode>
bool _get_gtk_ui_has_property(XmlDoc gtk_ui_doc, XmlNode node, const char* name)
{
    return _has_attribute(gtk_ui_doc, node, name);
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
XmlAttr _get_gtk_ui_get_property(XmlDoc gtk_ui_doc, XmlNode node, const char* name)
{
    return _get_attribute<XmlDoc, XmlNode, XmlAttr>(gtk_ui_doc, node, name);
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
const char* _get_gtk_ui_property_name(XmlDoc gtk_ui_doc, XmlNode node, XmlAttr attr)
{
    return _get_attribute_name<XmlDoc, XmlNode, XmlAttr>(gtk_ui_doc, node, attr);
}

template<typename XmlDoc, typename XmlNode, typename XmlAttr>
const char* _get_gtk_ui_property_value(XmlDoc gtk_ui_doc, XmlNode node, XmlAttr attr)
{
    return _get_attribute_value<XmlDoc, XmlNode, XmlAttr>(gtk_ui_doc, node, attr);
}

#endif
